<?php


namespace App\Models\CacheModel;


use App\Models\Api\BaseCache;
use Exception;
use think\Log;
use AstroTool\Cache\CacheManage;

/**
 * 月运模型
 * Class MonthFortune
 * @package App\Models\CacheModel
 */
class MonthFortune extends BaseCache
{
    protected $table = 'month_fortune';
    protected $cacheModel = 'fortune.fortune_month';


    /**
     * 获取运势缓存信息
     * @param array $map
     * @return array|bool|mixed
     * @throws Exception
     */
    public function getMonthFortune($map = [])
    {
        if (empty($map) || !isset($map['rid']) || !isset($map['month']))
        {
            return [];
        }

        if (strlen($map['month']) === 6)
        {
            $map['month'] = str_replace('-', '-0', $map['month']);
        }

        $idKey = $map['rid'] . ':' . $map['month'];
        // TODO ???? 若数据库中未查询到该数据，数据格式变成了数组，原格式为json字符串
        $data = CacheManage::getInstance()->setCacheConfig($this->cacheModel, $idKey)->getDataAndSet(function () use ($map)
        {
            return $this->getFortuneMonthByDb($map['rid'], $map['month']);
        });

        return $data;
    }

    /**
     * 获取月运信息
     * @param $rid
     * @param $month
     * @return mixed|string
     */
    public function getFortuneMonthByDb($rid, $month)
    {
        try
        {
            $data = $this->where(['rid' => $rid, 'month' => $month])->value('fortune');
        }
        catch (Exception $e)
        {
            Log::error('rid:' . $rid . ' month:' . $month . '数据未找到，请及时处理。');
            $data = '';
        }

        return $data;
    }

    /**
     * 获取订单备份档案信息
     * @param string $order_id
     * @return array|bool|mixed|string
     * @throws Exception
     */
    public function getOrderRecodeBackRecode($order_id)
    {
        return CacheManage::getInstance()->setCacheConfig('fortune.back_recode', $order_id)->getDataAndSet(function () use ($order_id)
        {
            try
            {
                return $this->from('month_fortune as m')
                    ->join('fortune_recode_back r', 'm.rid_back=r.id')
                    ->where(['m.order_id' => $order_id, 'm.type' => 1])
                    ->column('r.recode_info', 'r.id');
            }
            catch (\Exception $e)
            {
                return [];
            }
        });
    }

    /**
     * 获取档案月运解锁月份 v2.6.0
     * @param int $rid
     * @param int $isSimpleness 是否是精简版 0=>不是 1=>是
     * @return array
     * @throws Exception
     */
    public function getReocdeFortuneUnlockMonths(int $rid, $isSimpleness = 0): array
    {
        $unlockMonth = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel)
            ->setCacheKeyDetail('list_v2', $rid . ':' . $isSimpleness)
            ->setPage(-1)
            ->getListPageDataIds(function ($isCache = true, $sortType = 'desc') use ($rid, $isSimpleness)
            {
                try
                {
                    $fortuneMonth = $this->where('rid', (int)$rid)->where('is_simpleness', $isSimpleness)->where('status', '>', 0)->orderBy('id', 'asc')->pluck('month', 'id')->toArray();
                    $resData = [];
                    foreach ($fortuneMonth as $month => $id)
                    {
                        $resData[$month] = [
                            'id' => $id,
                            'month' => $month
                        ];
                    }

                    return $resData;
                }
                catch (\Exception $e)
                {
                    return [];
                }
            }, 'id', 0, 'list_v2');

        return array_keys($unlockMonth['data']);
    }

    /**
     * 批量获取 档案解锁月运详情 v2.6.0
     * @param int $rid
     * @param array $months
     * @param array $field
     * @param int $isSimpleness 是否是精简版 0=>不是 1=>是
     * @return array
     * @throws Exception
     */
    public function batchGetRecodeFortuneMonthInfo(int $rid, array $months, array $field = [], $isSimpleness = 0): array
    {
        $cacheKeys = [];
        foreach ($months as $monthItem)
        {
            $cacheKeys[] = $isSimpleness ? $rid . ':' . $monthItem . ':' . $isSimpleness : $rid . ':' . $monthItem; // 如果不是精简版key格式为 档案ID:解锁月   精简版为 档案ID:解锁月:1
        }

        if (empty($cacheKeys))
        {
            return [];
        }

        return CacheManage::getInstance()->setCacheConfig($this->cacheModel)->setCacheType('hash')
            ->batchGetCache($cacheKeys, function ($ids) use ($isSimpleness)
            {
                try
                {
                    $rid = 0;
                    $months = [];
                    foreach ($ids as $cacheKeyItem)
                    {
                        [$rid, $month] = explode(':', $cacheKeyItem);
                        $months[] = $month;
                    }

                    $fortuneData = $this->where('rid', (int)$rid)->where('is_simpleness', $isSimpleness)->whereIn('month', $months)->order('id asc')->column('*', 'id');

                    if (empty($fortuneData))
                    {
                        return [];
                    }
                    $backrids = array_unique(array_column($fortuneData, 'rid_back'));

                    $backRecode = $this->table('wechat_backup_07_18_14_43_00.app_fortune_recode_back')->whereIn('id', $backrids)->column('recode_info', 'id');
                    foreach ($backRecode as $backRid => $reocdeInfo)
                    {
                        $backRecode[$backRid] = \GuzzleHttp\json_decode($reocdeInfo, true);
                    }

                    $resFortuneData = [];
                    foreach ($fortuneData as $fortuneDatum)
                    {
                        $fortuneInfo = [
                            'id' => $fortuneDatum['id'],
                            'type' => $fortuneDatum['type'],
                            'order_id' => $fortuneDatum['order_id'],
                            'rid_back' => $fortuneDatum['rid_back'],
                            'status' => (int)$fortuneDatum['status'],
                            'rid' => $fortuneDatum['rid'],
                            'month' => $fortuneDatum['month'],
                            'fortune' => $fortuneDatum['fortune'],
                            'recode_info' => $backRecode[$fortuneDatum['rid_back']],
                        ];
                        $fRecode = $fortuneInfo['recode_info'];
                        // 档案唯一标示Key
                        $recodeUniqueKey = "{$fRecode['type']}:{$fRecode['year']}:{$fRecode['month']}:{$fRecode['day']}:{$fRecode['hour']}:{$fRecode['minute']}:{$fRecode['timezone']}:{$fRecode['ew']}:{$fRecode['long_deg']}:{$fRecode['long_min']}:{$fRecode['ns']}:{$fRecode['lat_deg']}:{$fRecode['lat_min']}:{$fRecode['is_summer']}";
                        if (isset($resFortuneData[$fortuneDatum['rid'] . ':' . $fortuneDatum['month']][$recodeUniqueKey]) && $fortuneInfo['status'] === 0)
                        {
                            continue;
                        }
                        $resFortuneData[$fortuneDatum['rid'] . ':' . $fortuneDatum['month'] . ($isSimpleness === 1 ? ":1" : '')][$recodeUniqueKey] = \GuzzleHttp\json_encode($fortuneInfo, JSON_UNESCAPED_UNICODE);
                    }

                    return $resFortuneData;
                }
                catch (\Exception $e)
                {
                    return [];
                }

            }, $field, 'list_details_v2');
    }

    /**
     * 获取档案 当前月份 月运信息（已解锁）
     * @param array $recode 档案信息
     * @param string $month 月
     * @param int $isSimpleness 是否是精简版 0=>不是 1=>是
     * @return array
     * @throws Exception
     */
    public function getFortuneMonthDetail(array $recode, string $month, $isSimpleness = 0)
    {
        $data = $this->batchGetRecodeFortuneMonthInfo((int)$recode['id'], [$month], [], $isSimpleness);

        if (empty($data))
        {
            return null;
        } else
        {
            $data = current($data);
        }

        $recodeUniqueKey = "{$recode['type']}:{$recode['year']}:{$recode['month']}:{$recode['day']}:{$recode['hour']}:{$recode['minute']}:{$recode['timezone']}:{$recode['ew']}:{$recode['long_deg']}:{$recode['long_min']}:{$recode['ns']}:{$recode['lat_deg']}:{$recode['lat_min']}:{$recode['is_summer']}";

        if (isset($data[$recodeUniqueKey]))
        {
            $fortuneInfo = \GuzzleHttp\json_decode($data[$recodeUniqueKey], true);
            if ($fortuneInfo['status'] > 0)
            {
                $fortuneInfo['recode_is_change'] = false;
                return $fortuneInfo;
            } else
            {
                unset($data[$recodeUniqueKey]);
            }
        }

        $resFortune = null;
        foreach ($data as $fortuneStr)
        {
            $fortuneInfo = \GuzzleHttp\json_decode($fortuneStr, true);
            if ($fortuneInfo['status'] > 0)
            {
                if (is_null($resFortune))
                {
                    $resFortune = $fortuneInfo;
                }

                if ($fortuneInfo['id'] > $resFortune['id'])
                {
                    $resFortune = $fortuneInfo;
                }
            }
        }

        $resFortune['recode_is_change'] = true;

        return $resFortune;
    }


    public function addFortune($insertData = [])
    {
        $status = true;
        if (empty($insertData))
        {
            return false;
        }
        try
        {
            // 先删除，后添加
            $this->where(['rid' => $insertData['rid'], 'month' => $insertData['month']])->delete();

            $this->insertGetId($insertData);
        }
        catch (\Exception $e)
        {
            $status = false;
            \think\Log::write('月运势写入数据库失败：' . $e->getMessage(), 'error', true);
            \think\Log::write('数据：' . var_export($insertData, true), 'error', true);

        }
        return $status;
    }

    public function addFortuneForYear($insertData = [], $map = [])
    {
        $status = true;
        if (empty($insertData))
        {
            return false;
        }
        try
        {
            // 先删除，后添加 rid=>$rid,month in ('2018-01',2,3,4,5,6,7,8,9,10,11,12)
            $this->where($map)->delete();
            // 年运入库的时候，批量入库
            $this->insertAll($insertData);
        }
        catch (\Exception $e)
        {
            $status = false;
            print('年运-月运势写入数据库失败：' . $e->getMessage() . PHP_EOL);
            \think\Log::write('年运-月运势写入数据库失败：' . $e->getMessage(), 'error', true);
            \think\Log::write('数据：' . var_export($insertData, true), 'error', true);
        }
        return $status;
    }
}
